package com.bf.threadPool;

import com.bf.utils.CommonService;
import com.bf.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
public class ThreadTransactionalUtilsItem implements Runnable {

    /**
     * 记录子线程第一次执行是否完成
     */
    private CountDownLatch count;

    /**
     * 保存每个线程的执行结果
     */
    private CopyOnWriteArrayList<Boolean> sonResult;

    /**
     * 记录主线程是否执行过判断每个线程的执行结果这个操作
     */
    private CountDownLatch mainCount;

    /**
     * 记录主线程对每个线程的执行结果的判断
     */
    private AtomicBoolean ifSubmit;

    /**
     * 声明该子线程的事务管理器
     */
    private DataSourceTransactionManager dataSourceTransactionManager;

    /**
     * 声明该线程事务的状态
     */
    private TransactionStatus status;

    /**
     * 记录子线程第二次执行是否完成
     */
    private CountDownLatch endCount;

    /**
     * 需要执行的方法
     */
    private CommonService commonService;


    /**
     * 子任务名称
     */
    private String jobName;

    private AtomicReference<Exception> exception;

    public ThreadTransactionalUtilsItem(CommonService commonService, CountDownLatch count, CopyOnWriteArrayList<Boolean> sonResult,
                                        CountDownLatch mainCount, AtomicBoolean ifSubmit, CountDownLatch endCount, String jobName, AtomicReference<Exception> exception) {
        this.commonService = commonService;
        this.count = count;
        this.sonResult = sonResult;
        this.mainCount = mainCount;
        this.ifSubmit = ifSubmit;
        this.endCount = endCount;
        this.jobName = jobName;
        this.exception = exception;
    }

    @Override
    public void run() {
        try {
            dataSourceTransactionManager = SpringUtils.getBean(DataSourceTransactionManager.class);
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            status = dataSourceTransactionManager.getTransaction(def);
            commonService.accept();
            sonResult.add(true);
        } catch (Exception e) {
            e.printStackTrace();
            sonResult.add(false);
            exception.set(e);
            log.info("==>任务：{}，执行出现异常！", jobName);
        } finally {
            // 当一个线程执行完了计数要减一不然这个线程会被一直挂起
            count.countDown();
            try {
                log.info("==>{}：准备就绪,任务名称：{},等待其他线程结果,判断是否事务提交", Thread.currentThread().getName(), jobName);
                mainCount.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                if (ifSubmit.get()) {
                    dataSourceTransactionManager.commit(status);
                    log.info("==>{}：事务提交,任务名称：{}", Thread.currentThread().getName(), jobName);
                } else {
                    dataSourceTransactionManager.rollback(status);
                    log.info("==>{}：事务回滚,任务名称：{}", Thread.currentThread().getName(), jobName);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                // 执行完所有逻辑，等待主线程执行
                endCount.countDown();
            }
        }
    }
}
